package models

import (
	"crypto/hmac"
	"crypto/sha1"
	"crypto/tls"
	"encoding/base64"
	"fmt"
	"gitchina/smartguard-api/errors"
	"gitchina/smartguard-api/util"
	"io/ioutil"
	"net/http"
	"net/url"
	"time"

	"github.com/pborman/uuid"
)

const (
	FUNC_OSS_INIT = "oss.init"
)

type OSS struct {
}

var credential string

func init() {
	//duration := time.Duration(time.Minute * 55)
	t1 := time.NewTimer(time.Second)
	client := &http.Client{Transport: &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}, Timeout: time.Duration(5 * time.Second)}
	go func() {
		for {
			select {
			case <-t1.C:
				if val, err := getCredential(client); err == nil {
					credential = val
				} else {
					util.WriteLog(errors.New(FUNC_OSS_INIT, err.Error()))
				}
				t1.Reset(time.Minute * 55)
			}
		}
	}()
}

func (oss OSS) Credential() string {
	return credential
}

func getCredential(client *http.Client) (c string, err error) {
	var resp *http.Response

	accessKeyID := "LTAI6h0CInVmVJ17"
	ts := time.Now().UTC().Format("2006-01-02T15:04:05Z")
	roleArn := "acs:ram::1159157335959216:role/ossrw"
	signNonce := uuid.New()

	tpl := "AccessKeyId=%s&Action=AssumeRole&Format=JSON&RoleArn=%s&RoleSessionName=client&SignatureMethod=HMAC-SHA1&SignatureNonce=%s&SignatureVersion=1.0&Timestamp=%s&Version=2015-04-01"
	tosign := "GET&%2F&" + url.QueryEscape(fmt.Sprintf(tpl, url.QueryEscape(accessKeyID), url.QueryEscape(roleArn), url.QueryEscape(signNonce), url.QueryEscape(ts)))
	hash := hmac.New(sha1.New, []byte("tmgBLZreLawsMQFIRaWEyjMjYiEPO7&"))
	hash.Write([]byte(tosign))
	sign := base64.StdEncoding.EncodeToString(hash.Sum(nil))
	tpl = "https://sts.aliyuncs.com/?SignatureVersion=1.0&Format=JSON&Timestamp=%s&RoleArn=%s&RoleSessionName=client&AccessKeyId=%s&SignatureMethod=HMAC-SHA1&Version=2015-04-01&Signature=%s&Action=AssumeRole&SignatureNonce=%s"
	val := fmt.Sprintf(tpl, url.QueryEscape(ts), url.QueryEscape(roleArn), url.QueryEscape(accessKeyID), url.QueryEscape(sign), signNonce)

	if resp, err = client.Get(val); resp != nil {
		defer resp.Body.Close()
	}
	if err == nil {
		var p []byte
		if p, err = ioutil.ReadAll(resp.Body); err == nil {
			c = string(p)
		}
	}
	return
}
